﻿namespace Smart.Utils.Net
{
    using System;
    using System.Net;
    using System.Net.Security;
    using System.Net.Sockets;
    using System.Runtime.CompilerServices;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    using System.Threading;

    public class SmtpClient2
    {
        private string errorMessage;
        private int ErrorNumber;
        private MailMessage2 mailMessage;
        private int Maxvalue;
        private NetworkStream networkStream;
        private string password;
        private SslStream secureStream;
        private int smtpPort;
        private string smtpServer;
        private Socket tcp_Socket;
        private int timeOut;
        private string userName;

        public event AuthenticateEventHandler AuthenticationBegan;

        public event AuthenticateEventHandler AuthenticationFinished;

        public event ConnectEventHandler ConnectionEstablished;

        public event ConnectEventHandler ConnectionEstablishing;

        public event ConnectToInternetEventHandler ConnectToInternet;

        public event DisconnectEventHandler Disconnected;

        public event DataTransferEventHandler EndedDataTransfer;

        public event ErrorEmailSentEventHandler ErrorEmailSent;

        public event SendProcessEventHandler SendProcess;

        public event DataTransferEventHandler StartedDataTransfer;

        public event SuccessEventHandler Successes;

        public event ThuEventHandler thu;

        public SmtpClient2()
        {
            this.SmtpServer = "";
            this.smtpPort = 0x19;
            this.timeOut = 60;
            this.userName = "";
            this.password = "";
            this.errorMessage = "";
            this.ErrorNumber = 0;
            this.Maxvalue = 12;
        }

        public SmtpClient2(string server)
        {
            this.smtpServer = server;
            this.smtpPort = 0x19;
            this.timeOut = 60;
            this.userName = "";
            this.password = "";
            this.errorMessage = "";
            this.ErrorNumber = 0;
            this.Maxvalue = 12;
        }

        public SmtpClient2(string server, int port)
        {
            this.smtpServer = server;
            this.smtpPort = port;
            this.timeOut = 60;
            this.userName = "";
            this.password = "";
            this.errorMessage = "";
            this.ErrorNumber = 0;
            this.Maxvalue = 12;
        }

        private string GetEmailInformation()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("MIME-Version: 1.0\r\n");
            builder.Append("From: <" + this.mailMessage.From + ">\r\n");
            builder.Append("To: " + this.mailMessage.To + "\r\n");
            if (this.mailMessage.CC.Length > 0)
            {
                builder.Append("Cc: " + this.mailMessage.CC + "\r\n");
            }
            builder.Append("Subject: " + this.mailMessage.Subject + "\r\n");
            builder.Append("Date: " + DateTime.Now.ToString("F") + "\r\n");
            switch (this.mailMessage.MailPriority)
            {
                case MailSendPriority.HIGH:
                    builder.Append("Priority: High\r\n");
                    break;

                case MailSendPriority.NORMAL:
                    builder.Append("Priority: Normal\r\n");
                    break;

                case MailSendPriority.LOW:
                    builder.Append("Priority: Low\r\n");
                    break;
            }
            string str = "--boundary_0_" + Guid.NewGuid().ToString();
            if (this.mailMessage.AttachmentCount > 0)
            {
                builder.Append("Content-Type: multipart/mixed; ");
                builder.Append("boundary=\"" + str + "\"\r\n");
                builder.Append("\r\n");
                builder.Append("--" + str + "\r\n");
            }
            switch (this.mailMessage.MailType)
            {
                case MailEncodingType.PLAINTEXT:
                    builder.Append("Content-Type: text/plain; ");
                    break;

                case MailEncodingType.HTML:
                    builder.Append("Content-Type: text/html; ");
                    break;
            }
            builder.Append("charset=utf-8 \r\n");
            builder.Append("Content-Transfer-Encoding: 8bit\r\n");
            builder.Append("\r\n");
            builder.Append(this.mailMessage.Message + "\r\n\r\n");
            for (int i = 0; i < this.mailMessage.AttachmentCount; i++)
            {
                builder.Append("--" + str + "\r\n");
                builder.Append(new Attachment(this.mailMessage.Attachments[i].ToString()).GetMimeMessage());
            }
            if (this.mailMessage.AttachmentCount > 0)
            {
                builder.Append("--" + str + "--");
            }
            builder.Append("\r\n.\r\n");
            return builder.ToString();
        }

        private string HTMLEncode(string data)
        {
            StringBuilder builder = new StringBuilder(data);
            builder.Replace("\x00e1", "&aacute;");
            builder.Replace("\x00e9", "&eacute;");
            builder.Replace("\x00ed", "&iacute;");
            builder.Replace("\x00f3", "&oacute;");
            builder.Replace("\x00fa", "&uacute;");
            builder.Replace("\x00f1", "&ntilde;");
            return builder.ToString();
        }

        private static bool OnCertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }

        private void RaiseAuthenticationBegan(string userName)
        {
            if (this.AuthenticationBegan != null)
            {
                this.AuthenticationBegan(this, userName);
            }
        }

        private void RaiseAuthenticationFinished(string userName)
        {
            if (this.AuthenticationFinished != null)
            {
                this.AuthenticationFinished(this, userName);
            }
        }

        private void RaiseConnectionEstablished(string smtpServer, int smtpPort)
        {
            if (this.ConnectionEstablished != null)
            {
                this.ConnectionEstablished(this, smtpServer, smtpPort);
            }
        }

        private void RaiseConnectionEstablishing(string smtpServer, int smtpPort)
        {
            if (this.ConnectionEstablishing != null)
            {
                this.ConnectionEstablishing(this, smtpServer, smtpPort);
            }
        }

        private void RaiseConnectToInternet()
        {
            if (this.ConnectToInternet != null)
            {
                this.ConnectToInternet(this);
            }
        }

        private void RaiseDisconnected(string smtpServer)
        {
            if (this.Disconnected != null)
            {
                this.Disconnected(this, smtpServer);
            }
        }

        private void RaiseEndedDataTransfer()
        {
            if (this.EndedDataTransfer != null)
            {
                this.EndedDataTransfer(this);
            }
        }

        private void RaiseErrorEmailSent(int Number, string Message)
        {
            if (this.ErrorEmailSent != null)
            {
                this.ErrorEmailSent(this, Number, Message);
            }
        }

        private void RaiseSendProcess(int Value, int Maxvalue)
        {
            if (this.SendProcess != null)
            {
                this.SendProcess(this, Value, Maxvalue);
            }
        }

        private void RaiseStartedDataTransfer()
        {
            if (this.StartedDataTransfer != null)
            {
                this.StartedDataTransfer(this);
            }
        }

        private void RaiseSuccesses()
        {
            if (this.Successes != null)
            {
                this.Successes(this);
            }
        }

        private void RaiseThuEventHandler()
        {
            if (this.thu != null)
            {
                this.thu();
            }
        }

        private void SendDataThroughNetworkStream(string msg)
        {
            try
            {
                byte[] bytes = Encoding.ASCII.GetBytes(msg);
                this.networkStream.Write(bytes, 0, bytes.Length);
            }
            catch (Exception exception)
            {
                this.RaiseErrorEmailSent(13, exception.Message);
            }
        }

        private void SendDataThroughSecureStream(string msg)
        {
            try
            {
                byte[] bytes = Encoding.UTF8.GetBytes(msg);
                this.secureStream.Write(bytes, 0, bytes.Length);
            }
            catch (Exception exception)
            {
                this.RaiseErrorEmailSent(14, exception.Message);
            }
        }

        public void SendMail(MailMessage2 mailMessage)
        {
            IPAddress[] hostAddresses;
            this.RaiseSendProcess(0, this.Maxvalue);
            bool flag = false;
            while (!flag)
            {
                this.RaiseConnectToInternet();
                if (Internet.IsConnectedToInternet())
                {
                    flag = true;
                }
                else
                {
                    this.ErrorEmailSent(this, 0, "Can't connect to internet....");
                    Thread.SpinWait(0xea60);
                }
            }
            this.RaiseSendProcess(1, this.Maxvalue);
            this.mailMessage = mailMessage;
            this.ErrorNumber = 0;
            this.tcp_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                hostAddresses = Dns.GetHostAddresses(this.smtpServer);
                this.RaiseSendProcess(2, this.Maxvalue);
            }
            catch (Exception)
            {
                this.ErrorNumber = 1;
                this.errorMessage = "Smtp server \"" + this.smtpServer + "\" does not exist.";
                this.RaiseErrorEmailSent(1, this.errorMessage);
                return;
            }
            IPEndPoint remoteEP = new IPEndPoint(hostAddresses[0], this.SmtpPort);
            this.RaiseConnectionEstablishing(this.smtpServer, this.smtpPort);
            try
            {
                this.tcp_Socket.Connect(remoteEP);
                this.RaiseSendProcess(3, this.Maxvalue);
            }
            catch
            {
                this.ErrorNumber = 1;
                this.errorMessage = string.Concat(new object[] { "Unable to connect to SMTP server: ", this.smtpServer, ",on port ", this.smtpPort, "." });
                this.RaiseErrorEmailSent(2, this.errorMessage);
            }
            this.networkStream = new NetworkStream(this.tcp_Socket);
            string responseText = "";
            string[] strArray = new string[] { "EHLO", "MAIL FROM:", "RCPT TO:", "DATA", "", "QUIT" };
            string[] strArray2 = new string[] { "250", "250", "250", "354", "250", "221" };
            string msg = "";
            bool flag2 = false;
            ASCIIEncoding encoding = new ASCIIEncoding();
            if (!this.WaitForResponse("220", ref responseText, true))
            {
                this.errorMessage = "Did not get welcome message from SMTP server: " + this.smtpServer + ".\r\nServer said: " + responseText;
                this.tcp_Socket.Close();
                this.ErrorNumber = 1;
                this.RaiseErrorEmailSent(3, this.errorMessage);
            }
            else
            {
                this.RaiseSendProcess(4, this.Maxvalue);
                this.RaiseConnectionEstablished(this.smtpServer, this.smtpPort);
                for (int i = 0; i < strArray.Length; i++)
                {
                    msg = strArray[i];
                    this.RaiseSendProcess((4 + i) + 1, this.Maxvalue);
                    switch (i)
                    {
                        case 0:
                            msg = msg + " " + Dns.GetHostEntry("127.0.0.1").HostName + "\r\n";
                            break;

                        case 1:
                            msg = msg + "<" + this.mailMessage.From + ">\r\n";
                            break;

                        case 2:
                            flag2 = true;
                            break;

                        case 3:
                            msg = msg + "\r\n";
                            break;

                        case 4:
                            msg = msg + this.GetEmailInformation();
                            break;

                        case 5:
                            msg = msg + "\r\n";
                            break;
                    }
                    if (flag2)
                    {
                        string[] strArray3;
                        int num2;
                        string str3 = "";
                        if (this.mailMessage.To.Length > 0)
                        {
                            strArray3 = this.mailMessage.To.Split(new char[] { ',', ';' });
                            num2 = 0;
                            while (num2 < strArray3.Length)
                            {
                                if (strArray3[num2].Trim() != "")
                                {
                                    str3 = "<" + strArray3[num2] + ">";
                                    msg = "RCPT TO: " + str3 + "\r\n";
                                    this.SendDataThroughSecureStream(msg);
                                    if (!this.WaitForResponse("250", ref responseText, false))
                                    {
                                        this.errorMessage = "Server rejected the email address: " + str3 + ".";
                                        this.tcp_Socket.Close();
                                        this.ErrorNumber = 1;
                                        this.RaiseErrorEmailSent(4, this.errorMessage);
                                    }
                                }
                                num2++;
                            }
                        }
                        if (this.mailMessage.CC.Length > 0)
                        {
                            strArray3 = this.mailMessage.CC.Split(new char[] { ',', ';' });
                            num2 = 0;
                            while (num2 < strArray3.Length)
                            {
                                str3 = "<" + strArray3[num2] + ">";
                                msg = "RCPT TO: " + str3 + "\r\n";
                                this.SendDataThroughSecureStream(msg);
                                if (!this.WaitForResponse("250", ref responseText, false))
                                {
                                    this.errorMessage = "Server rejected the email address: " + str3 + ".";
                                    this.tcp_Socket.Close();
                                    this.ErrorNumber = 1;
                                    this.RaiseErrorEmailSent(5, this.errorMessage);
                                }
                                num2++;
                            }
                        }
                        if (this.mailMessage.BCC.Length > 0)
                        {
                            strArray3 = this.mailMessage.BCC.Split(new char[] { ',', ';' });
                            for (num2 = 0; num2 < strArray3.Length; num2++)
                            {
                                str3 = "<" + strArray3[num2] + ">";
                                msg = "RCPT TO: " + str3 + "\r\n";
                                this.SendDataThroughSecureStream(msg);
                                if (!this.WaitForResponse("250", ref responseText, false))
                                {
                                    this.errorMessage = "Server rejected the email address: " + str3 + ".";
                                    this.tcp_Socket.Close();
                                    this.ErrorNumber = 1;
                                    this.RaiseErrorEmailSent(6, this.errorMessage);
                                }
                            }
                        }
                        flag2 = false;
                    }
                    else
                    {
                        switch (i)
                        {
                            case 0:
                                this.SendDataThroughNetworkStream(msg);
                                if (!this.WaitForResponse(strArray2[0], ref responseText, true))
                                {
                                    this.errorMessage = "Did not get " + strArray2[0] + " reply from server for command " + strArray[0] + ".\r\nServer said: " + responseText;
                                    this.tcp_Socket.Close();
                                    this.ErrorNumber = 1;
                                    this.RaiseErrorEmailSent(7, this.errorMessage);
                                }
                                else
                                {
                                    msg = "STARTTLS\r\n";
                                    this.SendDataThroughNetworkStream(msg);
                                    if (!this.WaitForResponse("220", ref responseText, true))
                                    {
                                        this.errorMessage = "Did not get 220 reply from server for command STARTTLS.\r\nServer said: " + responseText;
                                        this.tcp_Socket.Close();
                                        this.ErrorNumber = 1;
                                        this.RaiseErrorEmailSent(8, this.errorMessage);
                                    }
                                    else
                                    {
                                        this.secureStream = new SslStream(this.networkStream, true, new RemoteCertificateValidationCallback(SmtpClient2.OnCertificateValidation));
                                        this.secureStream.AuthenticateAsClient("localhost");
                                        if (this.secureStream.IsAuthenticated)
                                        {
                                            msg = "Ehlo " + Dns.GetHostEntry("127.0.0.1").HostName + "\r\n";
                                            this.SendDataThroughSecureStream(msg);
                                            if (!this.WaitForResponse(strArray2[0], ref responseText, false))
                                            {
                                                this.errorMessage = "Did not get " + strArray2[0] + " reply from server for command " + strArray[0] + ".\r\nServer said: " + responseText;
                                                this.tcp_Socket.Close();
                                                this.ErrorNumber = 1;
                                                this.RaiseErrorEmailSent(9, this.errorMessage);
                                            }
                                            else if (responseText.IndexOf("Auth Login", StringComparison.OrdinalIgnoreCase) >= 0)
                                            {
                                                msg = "Auth Login\r\n";
                                                this.SendDataThroughSecureStream(msg);
                                                if (!this.WaitForResponse("334", ref responseText, false))
                                                {
                                                    this.errorMessage = "Did not get 334 reply from server for AUTH LOGIN.\r\nServer said: " + responseText;
                                                    this.tcp_Socket.Close();
                                                    this.ErrorNumber = 1;
                                                    this.RaiseErrorEmailSent(10, this.errorMessage);
                                                }
                                                else
                                                {
                                                    msg = Convert.ToBase64String(encoding.GetBytes(this.userName)) + "\r\n";
                                                    this.RaiseAuthenticationBegan(this.userName);
                                                    this.SendDataThroughSecureStream(msg);
                                                    if (!this.WaitForResponse("334", ref responseText, false))
                                                    {
                                                        this.errorMessage = "Did not get 334 reply from server for UserName Confirmation.\r\nServer said: " + responseText;
                                                        this.tcp_Socket.Close();
                                                        this.ErrorNumber = 1;
                                                        this.RaiseErrorEmailSent(11, this.errorMessage);
                                                    }
                                                    else
                                                    {
                                                        msg = Convert.ToBase64String(encoding.GetBytes(this.password)) + "\r\n";
                                                        this.SendDataThroughSecureStream(msg);
                                                        if (!this.WaitForResponse("235", ref responseText, false))
                                                        {
                                                            this.errorMessage = "Did not get 235 reply from server for Password Confirmation.\r\nServer said: " + responseText;
                                                            this.tcp_Socket.Close();
                                                            this.ErrorNumber = 1;
                                                            this.RaiseErrorEmailSent(12, this.errorMessage);
                                                        }
                                                        else
                                                        {
                                                            this.RaiseAuthenticationFinished(this.userName);
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                break;

                            case 4:
                                this.RaiseStartedDataTransfer();
                                this.SendDataThroughSecureStream(msg);
                                if (!this.WaitForResponse(strArray2[i], ref responseText, false))
                                {
                                    this.errorMessage = "Did not get " + strArray2[i] + " reply from server for command " + strArray[i] + ".\r\nServer said: " + responseText;
                                    this.tcp_Socket.Close();
                                    this.ErrorNumber = 1;
                                    this.RaiseErrorEmailSent(13, this.errorMessage);
                                }
                                else
                                {
                                    this.RaiseEndedDataTransfer();
                                }
                                break;

                            default:
                                this.SendDataThroughSecureStream(msg);
                                if (!this.WaitForResponse(strArray2[i], ref responseText, false))
                                {
                                    this.errorMessage = "Did not get " + strArray2[i] + " reply from server for command " + strArray[i] + ".\r\nServer said: " + responseText;
                                    this.tcp_Socket.Close();
                                    this.ErrorNumber = 1;
                                    this.RaiseErrorEmailSent(14, this.errorMessage);
                                }
                                if ((i == 5) && this.tcp_Socket.Connected)
                                {
                                    this.tcp_Socket.Close();
                                    this.RaiseDisconnected(this.smtpServer);
                                }
                                break;
                        }
                    }
                }
            }
            if (this.tcp_Socket.Connected)
            {
                this.tcp_Socket.Close();
                this.RaiseDisconnected(this.smtpServer);
                this.RaiseSendProcess(11, this.Maxvalue);
            }
            this.RaiseSuccesses();
            this.RaiseSendProcess(12, this.Maxvalue);
        }

        public void SendMail(string from, string recipient, string subject, string body)
        {
            this.mailMessage = new MailMessage2(from, recipient, subject, body);
            this.SendMail(this.mailMessage);
        }

        private bool WaitForResponse(string responseCode, ref string responseText, bool isNetworkStream)
        {
            DateTime now = DateTime.Now;
            TimeSpan span = (TimeSpan) (DateTime.Now - now);
            byte[] buffer = new byte[0x400];
            ASCIIEncoding encoding = new ASCIIEncoding();
            int num = 0;
            while (span.Seconds < this.timeOut)
            {
                try
                {
                    if (this.networkStream.DataAvailable)
                    {
                        if (isNetworkStream)
                        {
                            num = this.networkStream.Read(buffer, 0, buffer.Length);
                        }
                        else
                        {
                            num = this.secureStream.Read(buffer, 0, buffer.Length);
                        }
                        responseText = encoding.GetString(buffer, 0, buffer.Length);
                        return responseText.Substring(0, responseCode.Length).Equals(responseCode);
                    }
                    span = (TimeSpan) (DateTime.Now - now);
                }
                catch (Exception exception)
                {
                    this.RaiseErrorEmailSent(14, exception.Message);
                    return false;
                }
            }
            return false;
        }

        public string Password
        {
            get
            {
                return this.password;
            }
            set
            {
                this.password = value;
            }
        }

        public int SmtpPort
        {
            get
            {
                return this.smtpPort;
            }
            set
            {
                this.smtpPort = value;
            }
        }

        public string SmtpServer
        {
            get
            {
                return this.smtpServer;
            }
            set
            {
                this.smtpServer = value;
            }
        }

        public int TimeOut
        {
            get
            {
                return this.timeOut;
            }
            set
            {
                this.timeOut = value;
            }
        }

        public string UserName
        {
            get
            {
                return this.userName;
            }
            set
            {
                this.userName = value;
            }
        }

        public int vError
        {
            get
            {
                return this.ErrorNumber;
            }
        }
    }
}

